package infra.dao.user;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;
import models.User;

public class UserDAO implements IUserDAO {

    /* Constants */
    private final String PATH = File.separator + "Application" + File.separator + "users.data";

    /* Utilities */
    private final File dataFile;
    private FileOutputStream fout;
    private FileInputStream fins;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;

    /* List of Users */
    LinkedList<User> usersList;

    /* Singleton Instance */
    private static UserDAO instance;

    private UserDAO() throws IOException {
        this.usersList = new LinkedList<User>();
        dataFile = new File(PATH);

        if (dataFile.exists()) {
            dataFile.mkdirs();
            dataFile.createNewFile();
        }

        usersList = getAll();
    }

    public static UserDAO getInstance() throws IOException {
        if (instance == null) {
            instance = new UserDAO();
        }
        return instance;
    }

    @Override
    public void createUser(User user) {
        usersList.add(user);

        try {
            fout = new FileOutputStream(dataFile);
            oos = new ObjectOutputStream(fout);

            oos.flush();
            oos.writeObject(usersList);
            oos.close();
            fout.close();
        } catch (IOException error) {
            System.err.println("[Error] On UserDAO.createUser:");
            System.err.println("Could not access the requested file.");
        }
    }

    @Override
    public User retrieveUserByIp(String ip) {
        User user = null;

        try {
            fins = new FileInputStream(dataFile);
            ois = new ObjectInputStream(fins);
            fins.reset();
            usersList = (LinkedList<User>) ois.readObject();

            for (User userFromList : usersList) {
                if (userFromList.getIp().equals(ip)) {
                    user = userFromList;
                    break;
                }
            }

            ois.close();
            fins.close();
        } catch (IOException | ClassNotFoundException erro) {
            System.err.println("[Error] On UserDAO.retrieveUserByIp:");
            System.err.println("Could not access the requested file.");
        }

        return user;
    }

    @Override
    public User retrieveUserByLogin(String login) {
        User user = null;

        try {
            fins = new FileInputStream(dataFile);
            ois = new ObjectInputStream(fins);
            fins.reset();
            usersList = (LinkedList<User>) ois.readObject();

            for (User userFromList : usersList) {
                if (userFromList.getLogin().equals(login)) {
                    user = userFromList;
                    break;
                }
            }

            ois.close();
            fins.close();
        } catch (IOException | ClassNotFoundException erro) {
            System.err.println("[Error] On UserDAO.retrieveUserByLogin:");
            System.err.println("Could not access the requested file.");
        }

        return user;
    }

    @Override
    public void updateUserByIp(String ip, User updatedUser) {
        for (User userFromList : usersList) {
            if (userFromList.getIp().equals(ip)) {
                userFromList = updatedUser;
                break;
            }
        }

        try {
            fout = new FileOutputStream(dataFile);
            oos = new ObjectOutputStream(fout);

            oos.flush();
            oos.writeObject(usersList);
            oos.close();
            fout.close();
        } catch (IOException error) {
            System.err.println("[Error] On UserDAO.updateUserByIp:");
            System.err.println("Could not access the requested file.");
        }
    }

    @Override
    public void updateUserByLogin(String login, User updatedUser) {
        for (User userFromList : usersList) {
            if (userFromList.getLogin().equals(login)) {
                userFromList = updatedUser;
                break;
            }
        }

        try {
            fout = new FileOutputStream(dataFile);
            oos = new ObjectOutputStream(fout);

            oos.flush();
            oos.writeObject(usersList);
            oos.close();
            fout.close();
        } catch (IOException error) {
            System.err.println("[Error] On UserDAO.updateUserByLogin:");
            System.err.println("Could not access the requested file.");
        }
    }

    @Override
    public void deleteUserByIp(String ip) {
        for (User userFromList : usersList) {
            if (userFromList.getIp().equals(ip)) {
                usersList.remove(userFromList);
                break;
            }
        }

        try {
            fout = new FileOutputStream(dataFile);
            oos = new ObjectOutputStream(fout);

            oos.flush();
            oos.writeObject(usersList);
            oos.close();
            fout.close();
        } catch (IOException error) {
            System.err.println("[Error] On UserDAO.deleteUserByIp:");
            System.err.println("Could not access the requested file.");
        }
    }

    @Override
    public void deleteUserByLogin(String login) {
        for (User userFromList : usersList) {
            if (userFromList.getLogin().equals(login)) {
                usersList.remove(userFromList);
                break;
            }
        }

        try {
            fout = new FileOutputStream(dataFile);
            oos = new ObjectOutputStream(fout);

            oos.flush();
            oos.writeObject(usersList);
            oos.close();
            fout.close();
        } catch (IOException error) {
            System.err.println("[Error] On UserDAO.deleteUserByLogin:");
            System.err.println("Could not access the requested file.");
        }
    }

    @Override
    public boolean ipUserExists(String Ip) {
        for (User userFromList : usersList) {
            if (userFromList.getIp().equals(Ip)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean loginUserExists(String login) {
        for (User userFromList : usersList) {
            if (userFromList.getLogin().equals(login)) {
                return true;
            }
        }

        return false;

    }

    @Override
    public LinkedList<User> getAll() {
        LinkedList<User> buffer = new LinkedList<>();

        if (dataFile.length() == 0) {
            return buffer;
        }

        try {
            fins = new FileInputStream(dataFile);
            ois = new ObjectInputStream(fins);
            fins.reset();
            buffer = (LinkedList<User>) ois.readObject(); //pega a lista do arquivo
            ois.close();
            fins.close();
        } catch (IOException | ClassNotFoundException error) {
            System.err.println("[Error] On UserDAO.getAll:");
            System.err.println("Could not access the requested file.");
        }
        
        return buffer;
    }
}
